package labox.innovation.gameserver.network.serverpackets;

import java.util.LinkedList;
import java.util.List;

import javolution.util.FastList;

import labox.innovation.config.Config;
import labox.innovation.gameserver.model.L2Effect;
import labox.innovation.gameserver.model.actor.L2Character;
import labox.innovation.gameserver.model.actor.L2Npc;
import labox.innovation.gameserver.model.actor.L2Summon;
import labox.innovation.gameserver.model.actor.instance.FuzeMonsterInstance;

/**
 * ע��NPCЭ��
 * 
 * @version $Revision: 1.7.2.4.2.9 $ $Date: 2005/04/11 10:05:54 $
 */
public abstract class AbstractNpcInfo extends L2GameServerPacket {

	private static final String _S__22_NPCINFO = "[S] 0c NpcInfo";

	protected int _x, _y;

	protected int _pAtkSpd;

	protected int _runSpd;

	protected long _attackTarget;

	public AbstractNpcInfo(L2Character cha) {
		_x = cha.getX();
		_y = cha.getY();
		_pAtkSpd = cha.getPAtkSpd();
		_runSpd = cha.getTemplate().baseRunSpd;
	}

	/* (non-Javadoc)
	 * @see labox.innovation.gameserver.serverpackets.ServerBasePacket#getType()
	 */
	@Override
	public String getType() {
		return _S__22_NPCINFO;
	}

	/**
	 * Packet for Npcs
	 */
	public static class NpcInfo extends AbstractNpcInfo {
		private L2Npc _npc;

		private List<Integer> effects;

		private int _dead;

		public NpcInfo(L2Npc cha, L2Character attacker) {
			super(cha);
			_npc = cha;
			if (cha.isInCombat()) {
				_attackTarget = _npc.getAI().getAttackTarget().getObjectId();
			}
			_dead = _npc.isDead() ? 1 : 0;
			effects = new LinkedList<Integer>();
			for (L2Effect ef : cha.getAllEffects()) {
				if (ef.hasContinuseEffectCartoon()) {
					effects.add(ef.getEffectCartoonId());
				}
			}
		}

		@Override
		protected void writeImpl() {
			writeByte(PTL_ABSTRACTNPCINFO);
			writeLong(_npc.getObjectId());
			writeByte(_npc.getTemplate()._animationId);//����ID
			writeString(_npc.getName());
			writeString(_npc.getTitle());
			writeShort(_x);
			writeShort(_y);
			writeByte(_runSpd);
			writeByte(_npc.getLevel());
			writeByte(_npc.getCurrentHpRadio());//TODO ���Ӧ���Ǳ���
			writeByte(_npc.getCurrentMpRadio());
			writeByte(_npc.getPhysicalAttackRange());
			writeByte(_pAtkSpd);
			if (_attackTarget != 0) {
				writeByte(1);
				writeLong(_attackTarget);
			} else {
				writeByte(0);
			}
			writeByte(_dead);
			writeByte(effects.size());
			for (int i = -1; ++i < effects.size();) {
				writeByte(effects.get(i));
			}
			effects.clear();
			effects = null;
		}
	}

	//	public static class TrapInfo extends AbstractNpcInfo {
	//		private L2Trap _trap;
	//
	//		public TrapInfo(L2Trap cha, L2Character attacker) {
	//			super(cha);
	//
	//			_trap = cha;
	//			_idTemplate = cha.getTemplate()._id;
	//			_isAttackable = cha.isAutoAttackable(attacker);
	//			_rhand = 0;
	//			_lhand = 0;
	//			_name = cha.getName();
	//			_title = cha.getOwner() != null ? cha.getOwner().getName() : "";
	//			_runSpd = _trap.getRunSpeed();
	//		}
	//
	//		@Override
	//		protected void writeImpl() {
	//			writeC(0x0c);
	//			writeD(_trap.getObjectId());
	//			writeD(_idTemplate + 1000000); // npctype id
	//			writeD(_isAttackable ? 1 : 0);
	//			writeD(_x);
	//			writeD(_y);
	//			writeD(_z);
	//			writeD(_heading);
	//			writeD(0x00);
	//			writeD(_mAtkSpd);
	//			writeD(_pAtkSpd);
	//			writeD(_runSpd);
	//			writeD(_walkSpd);
	//			writeD(_runSpd); // swim run speed
	//			writeD(_walkSpd); // swim walk speed
	//			writeD(_runSpd); // fly run speed
	//			writeD(_walkSpd); // fly walk speed
	//			writeD(_runSpd); // fly run speed
	//			writeD(_walkSpd); // fly walk speed
	//			writeF(_trap.getMovementSpeedMultiplier());
	//			writeF(_trap.getAttackSpeedMultiplier());
	//			writeF(_collisionRadius);
	//			writeF(_collisionHeight);
	//			writeD(_rhand); // right hand weapon
	//			writeD(_chest);
	//			writeD(_lhand); // left hand weapon
	//			writeC(1); // name above char 1=true ... ??
	//			writeC(1);
	//			writeC(_trap.isInCombat() ? 1 : 0);
	//			writeC(_trap.isAlikeDead() ? 1 : 0);
	//			writeC(_isSummoned ? 2 : 0); //  0=teleported  1=default   2=summoned
	//			writeS(_name);
	//			writeS(_title);
	//			writeD(0x00); // title color 0 = client default
	//
	//			writeD(_trap.getPvpFlag());
	//			writeD(_trap.getKarma());
	//
	//			writeD(_trap.getAbnormalEffect()); // C2
	//			writeD(0x00); //clan id
	//			writeD(0x00); //crest id
	//			writeD(0000); // C2
	//			writeD(0000); // C2
	//			writeC(0000); // C2
	//
	//			writeC(0x00); // Title color 0=client default 
	//
	//			writeF(_collisionRadius);
	//			writeF(_collisionHeight);
	//			writeD(0x00); // C4
	//			writeD(0x00); // C6
	//			writeD(0x00);
	//			writeD(0);//CT1.5 Pet form and skills
	//			writeC(0x01);
	//			writeC(0x01);
	//			writeD(0x00);
	//		}
	//	}
	//
	//	/**
	//	 * Packet for Decoys
	//	 */
	//	public static class DecoyInfo extends AbstractNpcInfo {
	//		private L2Decoy _decoy;
	//
	//		public DecoyInfo(L2Decoy cha) {
	//			super(cha);
	//
	//			_idTemplate = cha.getTemplate()._id;
	//			_decoy = cha;
	//			// _mAtkSpd = cha.getMAtkSpd(); on abstract constructor
	//			_pAtkSpd = cha.getOwner().getPAtkSpd();
	//			_runSpd = cha.getOwner().getRunSpeed();
	//
	//			if (_idTemplate < 13071 || _idTemplate > 13076) {
	//				if (Config.ASSERT)
	//					throw new AssertionError("Using DecoyInfo packet with an unsupported decoy template: " + _idTemplate);
	//				else
	//					throw new IllegalArgumentException("Using DecoyInfo packet with an unsupported decoy template: " + _idTemplate);
	//			}
	//
	//		}
	//
	//		@Override
	//		protected void writeImpl() {
	//			writeC(0x31);
	//			writeD(_x);
	//			writeD(_y);
	//			writeD(_z);
	//			writeD(_heading);
	//			writeD(_decoy.getObjectId());
	//			writeS(_decoy.getOwner().getAppearance().getVisibleName());
	//			writeD(_decoy.getOwner().getRace().ordinal());
	//			writeD(_decoy.getOwner().getAppearance().getSex() ? 1 : 0);
	//
	//			writeD(_decoy.getOwner().getClassIndex() == 0 ? _decoy.getOwner().getClassId().getId() : _decoy.getOwner().getBaseClass());
	//
	//			writeD(_decoy.getOwner().getInventory().getPaperdollItemId(Inventory.PAPERDOLL_HAIRALL));
	//			writeD(_decoy.getOwner().getInventory().getPaperdollItemId(Inventory.PAPERDOLL_HEAD));
	//			writeD(_decoy.getOwner().getInventory().getPaperdollItemId(Inventory.PAPERDOLL_RHAND));
	//			writeD(_decoy.getOwner().getInventory().getPaperdollItemId(Inventory.PAPERDOLL_LHAND));
	//			writeD(_decoy.getOwner().getInventory().getPaperdollItemId(Inventory.PAPERDOLL_GLOVES));
	//			writeD(_decoy.getOwner().getInventory().getPaperdollItemId(Inventory.PAPERDOLL_CHEST));
	//			writeD(_decoy.getOwner().getInventory().getPaperdollItemId(Inventory.PAPERDOLL_LEGS));
	//			writeD(_decoy.getOwner().getInventory().getPaperdollItemId(Inventory.PAPERDOLL_FEET));
	//			writeD(_decoy.getOwner().getInventory().getPaperdollItemId(Inventory.PAPERDOLL_BACK));
	//			writeD(_decoy.getOwner().getInventory().getPaperdollItemId(Inventory.PAPERDOLL_LRHAND));
	//			writeD(_decoy.getOwner().getInventory().getPaperdollItemId(Inventory.PAPERDOLL_HAIR));
	//			writeD(_decoy.getOwner().getInventory().getPaperdollItemId(Inventory.PAPERDOLL_HAIR2));
	//
	//			// T1 new d's
	//			writeD(_decoy.getOwner().getInventory().getPaperdollItemId(Inventory.PAPERDOLL_RBRACELET));
	//			writeD(_decoy.getOwner().getInventory().getPaperdollItemId(Inventory.PAPERDOLL_LBRACELET));
	//			writeD(_decoy.getOwner().getInventory().getPaperdollItemId(Inventory.PAPERDOLL_DECO1));
	//			writeD(_decoy.getOwner().getInventory().getPaperdollItemId(Inventory.PAPERDOLL_DECO2));
	//			writeD(_decoy.getOwner().getInventory().getPaperdollItemId(Inventory.PAPERDOLL_DECO3));
	//			writeD(_decoy.getOwner().getInventory().getPaperdollItemId(Inventory.PAPERDOLL_DECO4));
	//			writeD(_decoy.getOwner().getInventory().getPaperdollItemId(Inventory.PAPERDOLL_DECO5));
	//			writeD(_decoy.getOwner().getInventory().getPaperdollItemId(Inventory.PAPERDOLL_DECO6));
	//			// end of t1 new d's
	//
	//			// CT2.3
	//			writeD(0x00);
	//
	//			// c6 new h's
	//			writeD(_decoy.getOwner().getInventory().getPaperdollAugmentationId(Inventory.PAPERDOLL_UNDER));
	//			writeD(_decoy.getOwner().getInventory().getPaperdollAugmentationId(Inventory.PAPERDOLL_HEAD));
	//			writeD(_decoy.getOwner().getInventory().getPaperdollAugmentationId(Inventory.PAPERDOLL_RHAND));
	//			writeD(_decoy.getOwner().getInventory().getPaperdollAugmentationId(Inventory.PAPERDOLL_LHAND));
	//			writeD(_decoy.getOwner().getInventory().getPaperdollAugmentationId(Inventory.PAPERDOLL_GLOVES));
	//			writeD(_decoy.getOwner().getInventory().getPaperdollAugmentationId(Inventory.PAPERDOLL_CHEST));
	//			writeD(_decoy.getOwner().getInventory().getPaperdollAugmentationId(Inventory.PAPERDOLL_LEGS));
	//			writeD(_decoy.getOwner().getInventory().getPaperdollAugmentationId(Inventory.PAPERDOLL_FEET));
	//			writeD(_decoy.getOwner().getInventory().getPaperdollAugmentationId(Inventory.PAPERDOLL_BACK));
	//			writeD(_decoy.getOwner().getInventory().getPaperdollAugmentationId(Inventory.PAPERDOLL_LRHAND));
	//			writeD(_decoy.getOwner().getInventory().getPaperdollAugmentationId(Inventory.PAPERDOLL_HAIR));
	//			writeD(_decoy.getOwner().getInventory().getPaperdollAugmentationId(Inventory.PAPERDOLL_HAIR2));
	//
	//			// T1 new h's
	//			writeD(_decoy.getOwner().getInventory().getPaperdollAugmentationId(Inventory.PAPERDOLL_RBRACELET));
	//			writeD(_decoy.getOwner().getInventory().getPaperdollAugmentationId(Inventory.PAPERDOLL_LBRACELET));
	//			writeD(_decoy.getOwner().getInventory().getPaperdollAugmentationId(Inventory.PAPERDOLL_DECO1));
	//			writeD(_decoy.getOwner().getInventory().getPaperdollAugmentationId(Inventory.PAPERDOLL_DECO2));
	//			writeD(_decoy.getOwner().getInventory().getPaperdollAugmentationId(Inventory.PAPERDOLL_DECO3));
	//			writeD(_decoy.getOwner().getInventory().getPaperdollAugmentationId(Inventory.PAPERDOLL_DECO4));
	//			writeD(_decoy.getOwner().getInventory().getPaperdollAugmentationId(Inventory.PAPERDOLL_DECO5));
	//			writeD(_decoy.getOwner().getInventory().getPaperdollAugmentationId(Inventory.PAPERDOLL_DECO6));
	//
	//			// end of t1 new h's
	//			// CT2.3
	//			writeD(0x00);
	//			writeD(0x00);
	//			writeD(0x00);
	//
	//			writeD(_decoy.getOwner().getPvpFlag());
	//			writeD(_decoy.getOwner().getKarma());
	//
	//			writeD(_mAtkSpd);
	//			writeD(_pAtkSpd);
	//
	//			writeD(_decoy.getOwner().getPvpFlag());
	//			writeD(_decoy.getOwner().getKarma());
	//
	//			writeD(_runSpd);
	//			writeD(_walkSpd);
	//			writeD(50); // swim run speed
	//			writeD(50); // swim walk speed
	//			writeD(_runSpd); // fly run speed
	//			writeD(_walkSpd); // fly walk speed
	//			writeD(_runSpd); // fly run speed
	//			writeD(_walkSpd); // fly walk speed
	//			writeF(_decoy.getOwner().getMovementSpeedMultiplier()); // _activeChar.getProperMultiplier()
	//			writeF(_decoy.getOwner().getAttackSpeedMultiplier()); // _activeChar.getAttackSpeedMultiplier()
	//			L2Summon pet = _decoy.getPet();
	//			L2Transformation trans;
	//			if (_decoy.getOwner().getMountType() != 0 && pet != null) {
	//				writeF(pet.getTemplate().fCollisionRadius);
	//				writeF(pet.getTemplate().fCollisionHeight);
	//			} else if ((trans = _decoy.getOwner().getTransformation()) != null) {
	//				writeF(trans.getCollisionRadius());
	//				writeF(trans.getCollisionHeight());
	//			} else {
	//				writeF(_decoy.getOwner().getBaseTemplate().fCollisionRadius);
	//				writeF(_decoy.getOwner().getBaseTemplate().fCollisionHeight);
	//			}
	//
	//			writeD(_decoy.getOwner().getAppearance().getHairStyle());
	//			writeD(_decoy.getOwner().getAppearance().getHairColor());
	//			writeD(_decoy.getOwner().getAppearance().getFace());
	//
	//			writeS(_decoy.getOwner().getAppearance().getVisibleTitle());
	//
	//			writeD(_decoy.getOwner().getClanId());
	//			writeD(_decoy.getOwner().getClanCrestId());
	//			writeD(_decoy.getOwner().getAllyId());
	//			writeD(_decoy.getOwner().getAllyCrestId());
	//			// In UserInfo leader rights and siege flags, but here found nothing??
	//			// Therefore RelationChanged packet with that info is required
	//			writeD(0);
	//
	//			writeC(_decoy.getOwner().isSitting() ? 0 : 1); // standing = 1  sitting = 0
	//			writeC(_decoy.getOwner().isRunning() ? 1 : 0); // running = 1   walking = 0
	//			writeC(_decoy.getOwner().isInCombat() ? 1 : 0);
	//			writeC(_decoy.getOwner().isAlikeDead() ? 1 : 0);
	//
	//			writeC(_decoy.getOwner().getAppearance().getInvisible() ? 1 : 0); // invisible = 1  visible =0
	//
	//			writeC(_decoy.getOwner().getMountType()); // 1 on strider   2 on wyvern  3 on Great Wolf  0 no mount
	//			writeC(_decoy.getOwner().getPrivateStoreType()); //  1 - sellshop
	//
	//			writeH(_decoy.getOwner().getCubics().size());
	//			for (int id : _decoy.getOwner().getCubics().keySet())
	//				writeH(id);
	//
	//			writeC(0x00); // find party members
	//
	//			writeD(_decoy.getOwner().getAbnormalEffect());
	//
	//			writeC(_decoy.getOwner().getRecomLeft()); //Changed by Thorgrim
	//			writeH(_decoy.getOwner().getRecomHave()); //Blue value for name (0 = white, 255 = pure blue)
	//			writeD(_decoy.getOwner().getClassId().getId());
	//
	//			writeD(_decoy.getOwner().getMaxCp());
	//			writeD((int) _decoy.getOwner().getCurrentCp());
	//			writeC(_decoy.getOwner().isMounted() ? 0 : _decoy.getOwner().getEnchantEffect());
	//
	//			if (_decoy.getOwner().getTeam() == 1)
	//				writeC(0x01); //team circle around feet 1= Blue, 2 = red
	//			else if (_decoy.getOwner().getTeam() == 2)
	//				writeC(0x02); //team circle around feet 1= Blue, 2 = red
	//			else
	//				writeC(0x00); //team circle around feet 1= Blue, 2 = red
	//
	//			writeD(_decoy.getOwner().getClanCrestLargeId());
	//			writeC(_decoy.getOwner().isNoble() ? 1 : 0); // Symbol on char menu ctrl+I
	//			writeC(_decoy.getOwner().isHero() ? 1 : 0); // Hero Aura
	//
	//			writeC(_decoy.getOwner().isFishing() ? 1 : 0); //0x01: Fishing Mode (Cant be undone by setting back to 0)
	//			writeD(_decoy.getOwner().getFishx());
	//			writeD(_decoy.getOwner().getFishy());
	//			writeD(_decoy.getOwner().getFishz());
	//
	//			writeD(_decoy.getOwner().getAppearance().getNameColor());
	//
	//			writeD(0x00); // isRunning() as in UserInfo?
	//
	//			writeD(_decoy.getOwner().getPledgeClass());
	//			writeD(0x00); // ??
	//
	//			writeD(_decoy.getOwner().getAppearance().getTitleColor());
	//
	//			//writeD(0x00); // ??
	//
	//			writeD(_decoy.getOwner().isCursedWeaponEquipped() ? CursedWeaponsManager.getInstance().getLevel(_decoy.getOwner().getCursedWeaponEquippedId()) : 0x00);
	//			// T1 
	//			writeD(0x00);
	//
	//			writeD(_decoy.getOwner().getTransformationId());
	//		}
	//	}

	/**
	 * Packet for summons
	 */
	public static class SummonInfo extends AbstractNpcInfo {

		private L2Summon _summon;

		private List<Integer> effects;

		private int _dead;

		public SummonInfo(L2Summon cha, L2Character attacker) {
			super(cha);
			_summon = cha;
			if (cha.isInCombat()) {
				_attackTarget = cha.getAI().getAttackTarget().getObjectId();
			}
			_dead = cha.isDead() ? 1 : 0;
			effects = new LinkedList<Integer>();
			for (L2Effect ef : cha.getAllEffects()) {
				if (ef.hasContinuseEffectCartoon()) {
					effects.add(ef.getEffectCartoonId());
				}
			}
		}

		@Override
		protected void writeImpl() {
			writeByte(0x0c);
			writeLong(_summon.getObjectId());
			writeInt(_summon.getTemplate()._id); // npctype id

			writeString(_summon.getName());
			writeString(_summon.getTitle());
			writeShort(_x);
			writeShort(_y);
			writeByte(_runSpd);
			writeByte(_summon.getLevel());
			writeByte(_summon.getCurrentHpRadio());//TODO ���Ӧ���Ǳ���
			writeByte(_summon.getCurrentMpRadio());
			writeByte(_summon.getPhysicalAttackRange());
			writeByte(_pAtkSpd);
			if (_attackTarget != 0) {
				writeByte(1);
				writeLong(_attackTarget);
			} else {
				writeByte(0);
			}
			writeByte(_dead);
			writeByte(effects.size());
			for (int i = -1; ++i < effects.size();) {
				writeByte(effects.get(i));
			}
			effects.clear();
			effects = null;
		}
	}
}
